package com.hnit.service.Impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hnit.configs.ProductEs;
import com.hnit.mapper.ProductEsRepository;
import com.hnit.mapper.ProductMapper;
import com.hnit.service.CategoryService;
import com.hnit.service.ProductQueryVO;
import com.hnit.service.ProductService;
import com.hnit.web.Clients.IdServiceClient;
import com.hnit.web.Clients.UploadServiceClient;
import com.hnit.web.Clients.VectorStoreClient;
import com.hnit.web.DTO.ProductDTO;
import com.hnit.web.Utils.ResponseResult;
import com.hnit.web.bean.Product;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: shopping147_cloud
 * @description:
 * @author: zy
 * @create: 2025-07-24 19:32
 */
@Service                      //extends ServiceImpl<ProductMapper,Product>  自动注入了Mapper 等
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private IdServiceClient idGeneratorApi;
    @Autowired
    private UploadServiceClient fileUploadApi;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private VectorStoreClient vectorStoreClient;

    @Autowired
    private ProductEsRepository productEsRepository;

    @Autowired
    private ElasticsearchClient esClient;

    /**
     * 查询特价商品列表的实现
     * 特价商品定义为：当前价格低于原价，且商品状态为上架 (product_status = 1)
     * 结果按商品ID降序排列
     *
     * @return 特价商品列表
     */
    @Override
    public IPage<ProductDTO> getSpecialOfferProducts(ProductQueryVO queryVO) {
        // 创建分页对象
        Page<Product> page = new Page<>(queryVO.getCurrent(), queryVO.getSize());
        // 使用MyBatis-Plus的QueryWrapper构建查询条件
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        // 注意：这里的"price"和"original_price"是数据库列名
        // 修正：使用 apply 方法进行列与列之间的比较，避免将列名作为参数
        queryWrapper.apply("price < originalprice") //    where price < original_price
                .eq("productstatus", 1)      // product_status = 1
                .orderByDesc("productid");   // order by product_id DESC

        // 执行分页查询
        IPage<Product> productPage = productMapper.selectPage(page, queryWrapper);
        // 将实体分页结果转换为DTO分页结果
        return productPage.convert(product -> {
            ProductDTO dto = new ProductDTO();
            BeanUtils.copyProperties(product, dto);
            // 这里可以添加从其他服务获取分类名称的逻辑，例如通过Feign调用分类服务
            dto.setCategoryName(categoryService.getCategoryById(product.getCategoryId()).getCategoryName());
            return dto;
        });
    }

    /**
     * 分页查询商品
     *
     * @param queryVO 查询参数，包含商品名称、分类ID、商品状态、排序方式等
     * @return 商品DTO的分页结果
     */
    @Override
    public IPage<ProductDTO> listProductsPaged(ProductQueryVO queryVO) {
        // 创建分页对象
        Page<Product> page = new Page<>(queryVO.getCurrent(), queryVO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();

        // 根据商品名称模糊查询
        if (StringUtils.hasText(queryVO.getProductName())) {
            queryWrapper.like(Product::getProductName, queryVO.getProductName());
        }
        // 根据分类ID精确查询
        if (queryVO.getCategoryId() != null) {
            queryWrapper.eq(Product::getCategoryId, queryVO.getCategoryId());
        }
        // 根据商品状态查询
        if (queryVO.getProductStatus() != null) {
            queryWrapper.eq(Product::getProductStatus, queryVO.getProductStatus());
        }

        // 处理排序
        if (StringUtils.hasText(queryVO.getSortField())) {
            boolean isAsc = !"desc".equalsIgnoreCase(queryVO.getSortOrder());
            switch (queryVO.getSortField().toLowerCase()) {
                case "price":
                    queryWrapper.orderBy(true, isAsc, Product::getPrice);
                    break;
                case "productId":
                    queryWrapper.orderBy(true, isAsc, Product::getProductId);
                    break;
                // 可以添加其他排序字段
                default:
                    // 默认按商品ID降序
                    queryWrapper.orderByDesc(Product::getProductStatus);
                    break;
            }
        } else {
            // 默认排序
            queryWrapper.orderByDesc(Product::getProductId);
        }
        // 执行分页查询
        IPage<Product> productPage = productMapper.selectPage(page, queryWrapper);
        // 将实体分页结果转换为DTO分页结果
        return productPage.convert(product -> {
            ProductDTO dto = new ProductDTO();
            BeanUtils.copyProperties(product, dto);
            // 这里可以添加从其他服务获取分类名称的逻辑，例如通过Feign调用分类服务
            // dto.setCategoryName(categoryService.getCategoryNameById(product.getCategoryId()));
            return dto;
        });
    }

    /**
     * 上架商品 (新增商品)
     *
     * @param productDTO 待上架的商品信息
     * @return 上架成功后的商品DTO
     */
    @Override
    @Transactional // 开启事务
    public ProductDTO addProduct(ProductDTO productDTO) {
        // 1. 生成商品ID
        ResponseResult rr = this.idGeneratorApi.getNextId();
        if (rr.getCode() != 1) {
            throw new RuntimeException("商品ID生成失败");
        }
        Long productId = Long.parseLong(rr.getData().toString());
        productDTO.setProductId(productId);

        // 2. 模拟图片上传并设置URL
        //if (StringUtils.hasText(productDTO.getMainImage())) {
        ResponseResult rr2 = this.fileUploadApi.uploadFile(new MultipartFile[]{productDTO.getMainImageFile()});
        if (rr2.getCode() != 1) {
            throw new RuntimeException("商品主图片上传失败");
        }
        List<String> mainImages = (List<String>) rr2.getData();
        productDTO.setMainImage(mainImages.get(0));
        // }
        //  if (StringUtils.hasText(productDTO.getSubImages())) {
        // 假设subImages是逗号分隔的图片数据，这里需要循环上传
        //判断一下是否有子图id
        if (productDTO.getSubImageFiles() != null && productDTO.getSubImageFiles().length > 0) {
            MultipartFile[] subImageFiles = productDTO.getSubImageFiles();
            ResponseResult rr3 = this.fileUploadApi.uploadFile(subImageFiles);
            List<String> subImages = (List<String>) rr3.getData();
            StringBuilder uploadedSubImages = new StringBuilder();
            for (String imgData : subImages) {
                if (StringUtils.hasText(imgData)) {
                    uploadedSubImages.append(imgData).append(",");
                }
            }
            if (uploadedSubImages.length() > 0) {
                uploadedSubImages.setLength(uploadedSubImages.length() - 1); // 移除最后一个逗号
            }
            productDTO.setSubImages(uploadedSubImages.toString());
        }

        //  }
        // 3. 设置默认状态为上架
        if (productDTO.getProductStatus() == null) {
            productDTO.setProductStatus(1); // 默认上架
        }
        // 4. 确保价格不为空
        if (productDTO.getPrice() == null) {
            productDTO.setPrice(BigDecimal.ZERO);
        }
        // 5. 将DTO转换为实体
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product);
        // 6. 插入数据库
        int result = productMapper.insert(product);
        if (result > 0) {
            // 插入成功后，返回包含完整信息的DTO
            BeanUtils.copyProperties(product, productDTO);

            // 7. 插入向量数据库
            Map<String, Object> jsonData = new HashMap<>();
            jsonData.put("title", product.getProductName());
            jsonData.put("content", product.toString());
            jsonData.put("category", productDTO.getCategoryName());
            vectorStoreClient.addJsonData(jsonData);

            //同步数据到ES
            ProductEs productEs = new ProductEs();
            BeanUtils.copyProperties(product, productEs);
            // 从 DTO 中获取 categoryName，因为 Product 实体中没有这个字段
            productEs.setCategoryName(productDTO.getCategoryName());
            productEsRepository.save(productEs);

            return productDTO;
        } else {
            throw new RuntimeException("商品上架失败");
        }
    }

    /**
     * 切换商品上下架状态
     *
     * @param productId 商品ID
     * @return 是否操作成功
     */
    @Override
    @Transactional
    public boolean changeStatusProduct(Long productId) {
        // 1. 根据 productId 查询当前商品信息
        Product product = productMapper.selectById(productId);
        if (product == null) {
            // 商品不存在，直接返回 false
            return false;
        }

        // 2. 获取当前状态，并确定新的状态
        Integer currentStatus = product.getProductStatus();
        Integer newStatus = (currentStatus == 1) ? 0 : 1; // 如果当前是上架(1)，则新状态为下架(0)；否则为上架(1)

        // 3. 构建更新条件，只更新状态
        LambdaUpdateWrapper<Product> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Product::getProductId, productId)
                .set(Product::getProductStatus, newStatus);

        // 4. 执行更新
        int result = productMapper.update(null, updateWrapper);
        if (result > 0) {
            // 5. 如果数据库更新成功，同步更新 Elasticsearch
            // 获取最新的商品数据（因为可能需要其他字段，这里重新查询一次）
            product.setProductStatus(newStatus);

            ProductEs productEs = new ProductEs();
            BeanUtils.copyProperties(product, productEs);
            productEsRepository.save(productEs);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新商品信息
     *
     * @param productDTO 待更新的商品信息
     * @return 更新成功后的商品DTO
     */
    @Override
    @Transactional
    public ProductDTO updateProduct(ProductDTO productDTO) {
        if (productDTO.getProductId() == null) {
            throw new IllegalArgumentException("商品ID不能为空，无法更新");
        }

        if (productDTO.getMainImageFile() != null) {
            ResponseResult rr2 = this.fileUploadApi.uploadFile(new MultipartFile[]{productDTO.getMainImageFile()});
            if (rr2.getCode() != 1) {
                throw new RuntimeException("商品主图片上传失败");
            }
            List<String> mainImages = (List<String>) rr2.getData();
            productDTO.setMainImage(mainImages.get(0));
        }

        if (productDTO.getSubImageFiles() != null && productDTO.getSubImageFiles().length > 0) {
            // 假设subImages是逗号分隔的图片数据，这里需要循环上传
            MultipartFile[] subImageFiles = productDTO.getSubImageFiles();
            ResponseResult rr3 = this.fileUploadApi.uploadFile(subImageFiles);
            List<String> subImages = (List<String>) rr3.getData();
            StringBuilder uploadedSubImages = new StringBuilder();
            for (String imgData : subImages) {
                if (StringUtils.hasText(imgData)) {
                    uploadedSubImages.append(imgData).append(",");
                }
            }
            if (uploadedSubImages.length() > 0) {
                uploadedSubImages.setLength(uploadedSubImages.length() - 1); // 移除最后一个逗号
            }
            productDTO.setSubImages(uploadedSubImages.toString());
        }

        // 将DTO转换为实体
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product);

        // 执行数据库更新
        int result = productMapper.updateById(product);
        if (result > 0) {
            // 更新成功后，返回最新的商品信息
            ProductDTO updatedProductDTO = getProductById(productDTO.getProductId());

            // 同步数据到 Elasticsearch
            ProductEs productEs = new ProductEs();
            BeanUtils.copyProperties(updatedProductDTO, productEs);
            productEsRepository.save(productEs);

            return updatedProductDTO;
        } else {
            throw new RuntimeException("商品更新失败，商品ID: " + productDTO.getProductId());
        }
    }

    /**
     * ES搜索商品 (只搜索上架商品，productStatus=1)
     * @param keyword 搜索关键词，会搜索商品名称和详情描述
     * @param current 当前页码 (从1开始)
     * @param size 每页大小
     * @return 商品DTO分页结果
     */
    @Override
    public IPage<ProductDTO> searchProducts(String keyword, Integer current, Integer size) {

        // 修复分页参数：ES 的 from 参数是偏移量，需要用 (页码 - 1) * 每页大小 来计算
        int from = (current - 1) * size;

        Query query;
        // 基础查询：始终只搜索 productStatus=1 的商品
        if (keyword == null || keyword.trim().isEmpty()) {
            // 如果没有关键词，只按 productStatus=1 过滤
            query = Query.of(q -> q
                    .bool(b -> b
                            .filter(f -> f
                                    .term(t -> t.field("productStatus").value(1))
                            )
                    )
            );
        } else {
            // 有关键词时，使用 multi_match 进行关键词搜索，并用 productStatus=1 进行过滤
            query = Query.of(q -> q
                    .bool(b -> b
                            .must(m -> m
                                    .multiMatch(mm -> mm
                                            .fields("productName", "productDesc")
                                            .query(keyword)
                                            .operator(Operator.Or)
                                    )
                            )
                            .filter(f -> f
                                    .term(t -> t.field("productStatus").value(1))
                            )
                    )
            );
        }

        // 执行 ES 查询
        SearchResponse<ProductDTO> response;
        try {
            response = esClient.search(s -> s
                            .index("product")
                            .query(query)
                            .from(from) // 使用正确的 from 偏移量
                            .size(size),
                    ProductDTO.class);
        } catch (IOException e) {
            // 捕获异常，抛出自定义异常或记录日志
            e.printStackTrace();
            throw new RuntimeException("ES 查询失败", e);
        }

        // 构建 IPage 返回
        List<ProductDTO> records = response.hits().hits().stream()
                .map(hit -> hit.source())
                .collect(Collectors.toList());

        long total = response.hits().total() != null ? response.hits().total().value() : 0;

        Page<ProductDTO> pageResult = new Page<>(current, size, total);
        pageResult.setRecords(records);

        return pageResult;
    }
// 这是最常见的问题，你的代码中有一个关键的分页参数错误。
//Elasticsearch 分页机制: Elasticsearch 的 from 参数是偏移量（offset），而不是页码。
//你的代码: esClient.search(s -> s.index("product").query(query).from(current).size(size))
//当 current 为 1 时，from 也是 1。这意味着你跳过了第一个结果，直接从第二个结果开始。
//当 current 为 2 时，from 是 2。你跳过了前两个结果，从第三个开始。
//正确的做法: from 应该等于 (current - 1) * size。
//当 current 为 1 时，from = (1 - 1) * size = 0，从第一个结果开始，这是正确的。
//当 current 为 2 时，from = (2 - 1) * size = size，从第 size+1 个结果开始，这也是正确的。

    /**
     * 根据商品ID获取商品详情
     *
     * @param productId 商品ID
     * @return 商品DTO
     */
    @Override
    public ProductDTO getProductById(Long productId) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            return null;
        }
        ProductDTO dto = new ProductDTO();
        BeanUtils.copyProperties(product, dto);
        return dto;
    }
}